home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
clink120.zip
/
SEALINK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-08-24
|
23KB
|
608 lines
/* SEAlink - Sliding window file transfer protocol
Version 1.20, created on 08/05/87 at 17:51:40
Copyright 1986,87 by System Enhancement Associates; ALL RIGHTS RESERVED
By: Thom Henderson
Description:
This file contains a set of routines to illustrate the SEAlink
sliding window file transfer protocol. SEAlink is fully backward
compatible to XMODEM, and can be easily adapted to most XMODEM
variants.
The intent of SEAlink is to provide a file transfer protocol that
does not suffer from propagation delays, such as are introduced
by satellite relays or packet switched networks.
Instructions:
Two routines are provided to implement SEAlink file transfers.
int xmtfile(name) /+ transmit a file +/
char *name; /+ name of file to transmit +/
This routine is used to send a file. One file is sent at a time.
If the name is blank (name is null or *name points to a null),
then only an end of transmission marker is sent.
This routine returns a one if the file is successfully
transmitted, or a zero if a fatal error occurs.
char *rcvfile(name) /+ receive a file +/
char *name; /+ name of file (optional) +/
This routine is used to receive a file. One file is received.
The name, if given, takes precedence and will be the name of
the resulting file. If the name is blank (name is null or *name
points to a null), then the name given by the transmitter is used.
If the transmitter does not give a name, then the file transfer
is aborted.
This routine returns a pointer to the name of the file that
was received. If the file transfer is not successful, then
a null pointer is returned.
The pointer returned by rcvfile() points to a static data buffer.
This does not have to be freed (and should not be), but it will
be overwritten the next time rcvfile() is called.
The rcvfile() function works on a temporary file whose name is
the same as the final file, but with a dash ("-") added at the
beginning. If a file transfer is aborted, then this temporary
file will be retained. An aborted file transfer will not harm
a pre-existing file of the same name.
Programming notes:
These routines can be used for either single or multiple file
transfers.
To send multiple files, send each one one at a time until either
a transmit fails or all files are sent. If all files are sent,
then signal the end by calling xmtfile() with a null pointer.
To receive multiple files, call rcvfile() repeatedly until it
returns a null pointer.
These routines pass a "block zero", which contains information
about the original file name, size, and date/time of last
modification. If you cannot implement block zero, then you can
leave it out. If you cannot set any given field in block zero
when transmitting, then you should leave it set to zeros. If you
cannot use any given field of block zero when receiving, then
you should ignore it.
These routines are fully compatible with XMODEM, including the
original checksum method and later CRC adaptations. It can be
easily adapted to Modem7 protocol by adding a Modem7 filename
transfer shell, though we do not recommend it. The underlying
logic, of course, can be adapted to almost any variant of XMODEM.
License:
You are granted a license to use this code in your programs, and
to adapt it to your particular situation and needs, subject only
to the following conditions:
1) You must refer to it as the SEAlink protocol, and you must
give credit to System Enhancement Associates.
2) If you modify it in such a way that your version cannot
converse with the original code as supplied by us, then
you should refer to it as "SEAlink derived", or as a
"variation of SEAlink", or words to that effect.
In short, we're not asking for any money, but we'd like to
get some credit for our work.
Language:
Computer Innovations Optimizing C86
*/
#include <stdio.h>
#include "fstat.h"
#include <time.h>
struct zeros /* block zero data structure */
{ long flen; /* file length */
long fstamp; /* file date/time stamp */
char fnam[17]; /* original file name */
char prog[15]; /* sending program name */
char noacks; /* true if ACKing not required */
char fill[87]; /* reserved for future use */
} ;
#define ACK 0x06
#define NAK 0x15
#define SOH 0x01
#define EOT 0x04
#define WINDOW 6 /* normal window size */
static int outblk; /* number of next block to send */
static int ackblk; /* number of last block ACKed */
static int blksnt; /* number of last block sent */
static int slide; /* true if sliding window */
static int ackst; /* ACK/NAK state */
static int numnak; /* number of sequential NAKs */
static int chktec; /* check type, 1=CRC, 0=checksum */
static int toterr; /* total number of errors */
static int ackrep; /* true when ACK or NAK reported */
static int ackseen; /* count of sliding ACKs seen */
char *progname = "Your name here"; /* name of sending program */
int ackless = 0; /* true if ACKs not required */
/* File transmitter logic */
int xmtfile(name) /* transmit a file */
char *name; /* name of file to send */
{
FILE *f, *fopen(); /* file to send */
long t1, timerset(); /* timers */
int endblk; /* block number of EOT */
struct filstat fst; /* data about file */
struct zeros zero; /* block zero data */
if(name && *name) /* if sending a file */
{ if(!(f=fopen(name,"rb")))
{ printf(" Can't read %s\n",name);
return 0;
}
setmem(&zero,sizeof(zero),0); /* clear out data block */
filestat(name,&fst); /* get file statistics */
zero.flen = fst.fs_fsize;
zero.fstamp = fst.fs_abs;
strcpy(zero.fnam,fst.fs_fname);
strcpy(zero.prog,progname);
zero.noacks = ackless;
endblk = ((zero.flen+127)/128) + 1;
printf(" Ready to send %d blocks of %s\n",endblk-1,zero.fnam);
}
else endblk = 0; /* fake for no file */
outblk = 1; /* set starting state */
ackblk = -1;
blksnt = slide = ackst = numnak = toterr = ackrep = ackseen = 0;
chktec = 2; /* undetermined */
t1 = timerset(300); /* time limit for first block */
printf(" Waiting...\r");
while(ackblk<endblk) /* while not all there yet */
{ if(!carrier())
{ printf("\n Lost carrier\n");
goto abort;
}
if(key_scan()!=EOF)
{ if((key_getc()&0xff)==27)
{ printf("\n Aborted by operator\n");
goto abort;
}
}
if(timeup(t1))
{ printf("\n Fatal timeout\n");
goto abort;
}
if(outblk <= ackblk + (slide? WINDOW : 1))
{ if(out